package com.zxc.search.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.search.dtos.UserSearchDto;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.thread.AppThreadLocalUtil;
import com.zxc.search.service.ApArticleSearchService;
import com.zxc.search.service.ApUserSearchService;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;

@Slf4j
@Service
public class ApArticleSearchServiceImpl implements ApArticleSearchService {

    @Resource
    private RestHighLevelClient restHighLevelClient;
    @Resource
    private ApUserSearchService apUserSearchService;

    @Override
    public ResponseResult search(UserSearchDto userSearchDto) {
        //记录日志：开始执行搜索文章的方法
        log.info("开始执行搜索文章的方法。");
        if (userSearchDto == null || StringUtil.isNullOrEmpty(userSearchDto.getSearchWords())) {
            //记录日志：错误，搜索关键词为空
            log.error("错误：搜索词为空。");
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        ApUser apUser = AppThreadLocalUtil.getUser();
        if (apUser != null && userSearchDto.getFromIndex() == 0) {

            apUserSearchService.insert(userSearchDto.getSearchWords(), apUser.getId());
        }

        // 创建一个指向 "app_info_article" 索引的搜索请求
        SearchRequest searchRequest = new SearchRequest("app_info_article");

        // 创建 SearchSourceBuilder，以便在其中设置搜索相关的各类参数
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        // 创建 BoolQueryBuilder，用来组合多种查询条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        // 创建 QueryStringQueryBuilder，设定搜索关键词及相关的字段
        QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(userSearchDto.getSearchWords())
                .field("content")
                .field("title")
                .defaultOperator(Operator.OR);

        // 对 BoolQueryBuilder 添加 must 条件，即查询结果必须满足的条件
        boolQueryBuilder.must(queryStringQueryBuilder);

        // 创建 RangeQueryBuilder，设定对 "publishTime" 字段的查询条件
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime").lt(userSearchDto.getMinBehotTime().getTime());


        // 对 BoolQueryBuilder 添加 filter 过滤器，即结果需满足的过滤条件
        boolQueryBuilder.filter(rangeQueryBuilder);
        // 设置搜索结果的起始位置和数量（即分页）
        searchSourceBuilder.from(0);
        searchSourceBuilder.size(userSearchDto.getPageSize());
        // 设置搜索结果以 "publishTime" 排序，顺序为降序
        searchSourceBuilder.sort("publishTime", SortOrder.DESC);


        // 创建 HighlightBuilder，用来设置搜索结果的高亮显示
        HighlightBuilder highlightBuilder = new HighlightBuilder();

        highlightBuilder.field("title");
        // 设定高亮显示的标签样式
        highlightBuilder.preTags("<font style='color:red;font-size:inherit;'>");
        highlightBuilder.postTags("</font>");

        // 将 HighlightBuilder 添加至 SearchSourceBuilder
        searchSourceBuilder.highlighter(highlightBuilder);

        // 将 SearchSourceBuilder 添加至 SearchRequest
        searchSourceBuilder.query(boolQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = null;

        try {
            //记录日志：开始执行搜索
            log.info("开始执行搜索。");
            searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            //记录日志：搜索出现异常
            log.error("搜索过程中出现异常", e);
            e.printStackTrace();
        }

        ArrayList<Map> list = new ArrayList<>();
        SearchHit[] hits = searchResponse.getHits().getHits();
        for (SearchHit hit : hits) {
            String json = hit.getSourceAsString();
            Map map = JSON.parseObject(json, Map.class);
            if (hit.getHighlightFields() != null && hit.getHighlightFields().size() > 0) {
                Text[] titles = hit.getHighlightFields().get("title").getFragments();
                String title = StringUtils.join(titles);
                map.put("h_title", title);
            } else {
                map.put("h_title", map.get("title"));
            }
            list.add(map);
        }
        //记录日志：搜索完成
        log.info("搜索完成。返回结果数量:{}", list.size());
        return ResponseResult.okResult(list);
    }
}
